#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
BaseHandler
要获得的中间件等特性需继承这些handler
"""
from db import session_scope
from tornado.web import RequestHandler
from tornado.gen import coroutine, Return, Future
from utils.cephRados import CephConnection
from tornado.websocket import WebSocketHandler
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
from tornado.web import HTTPError

POOLTHREADNUM = 4


class SyncCeph(object):
    """异步化的ceph Client对象"""

    def __init__(self, executor):
        self.executor = executor

    def __getattr__(self, item):
        @coroutine
        def client(*args):
            ceph = yield self.executor.submit(CephConnection.instance)
            if 'sync' in item:
                res = yield getattr(ceph, item)(*args)
            else:
                res = yield self.executor.submit(getattr(ceph, item), *args)
            raise Return(res)

        return client


class BaseClass(object):
    executor = ThreadPoolExecutor(POOLTHREADNUM)

    @property
    def _id(self):
        return id(self)

    @property
    def db(self):
        with session_scope() as session:
            return session

    @coroutine
    def asyncdb(self, fn):
        def _lambda():
            with session_scope() as session:
                return fn(session)

        res = yield self.executor.submit(_lambda)
        raise Return(res)

    @coroutine
    def exception_middlewares(self):
        if hasattr(self, 'exc_middlewares'):
            return self.exc_middlewares
        else:
            return tuple()

    def cache(self, *args):
        return self.application._get_redis(*args)

    @property
    def middlewares(self):
        if hasattr(self, 'middleware'):
            return self.application.middlewares + self.middleware
        else:
            return self.application.middlewares

    @coroutine
    def prepare(self):
        middlewares = self.middlewares
        if isinstance(middlewares, Future):
            middlewares = yield middlewares
        for middleware in middlewares:
            if hasattr(middleware, 'process_request'):
                if hasattr(middleware.process_request, '__call__'):
                    try:
                        future = yield self.executor.submit(middleware.process_request, *(self,))
                        while isinstance(future, Future):
                            future = yield future
                    except Exception as e:
                        raise HTTPError(401, e.message)

    @coroutine
    def finish(self, chunk=None):
        middlewares = self.middlewares
        if isinstance(middlewares, Future):
            middlewares = yield middlewares
        for middleware in middlewares:
            if hasattr(middleware, 'process_response'):
                if hasattr(middleware.process_response, '__call__'):
                    try:
                        future = yield self.executor.submit(middleware.process_response, *(self,))
                        while isinstance(future, Future):
                            future = yield future
                    except Exception as e:
                        raise HTTPError(401, e.message)
        errs = (401, 402, 500)
        if chunk:
            for err in errs:
                if str(err) in chunk:
                    return
        super(BaseClass, self).finish(chunk)

    @property
    def ceph(self):
        return SyncCeph(self.executor)

    @run_on_executor
    def commit(self):
        self.application.db.commit()


class BaseRequestHandler(BaseClass, RequestHandler):
    '''用于restfull请求处理的基本类'''
    SUPPORTED_METHODS = ("GET", "HEAD", "POST", "DELETE", "PATCH", "PUT",)
    pass


class BaseWebSocketHandler(BaseClass, WebSocketHandler):
    '''用于长链接的基本类'''
    pass
